/*****************************
Req 630: OOR Release  146
Dev: Bibhudutta Mishra
Purpose: To update the Opportunities according to the Booking dates
Version: 1.0
******************************/
global class OOROrderBookingDatesUpdate implements Database.Batchable<sObject>{

public   String query;
public   Set<String> YearStringBatch;
global database.querylocator start(Database.BatchableContext BC){
     
     return Database.getQueryLocator(query);

}
global void execute(Database.BatchableContext BC, List<sObject> scope){
    List<Opportunity> Opptys= New List<Opportunity>();// List for Querying all OOR Opportunity with Submitted Date not equals null    
    List<Opportunity> OpptystoUpdate= New List<Opportunity>();//List to store the Updated Opportunites
    Map<String,Date> bookingdatesmap = New Map<String,Date>(); //Map to Store all the Bookind Date Object's Booking Month and Booking Closing Date
    String month; // Variable for Storing Month Value of the Submitted Date
    List<String> MonthList = new List<String>();
    Map<String,Integer> MonthYearMap = new Map<String,Integer>();
    Date myDate= Date.Today();       
    String year = String.ValueOf(myDate.Year());
    //Map<Integer,String> MonthMap = new Map<Integer,String>();
    Set<String> Yearset = new  Set<String>();
    for(sObject s : scope){
        Opportunity a = (Opportunity)s;
        Opptys.add(a);
        
        //Added Condition for Completed Date
        if(a.Order_Completion_Date__c != NULL){
               Yearset.add(String.ValueOf(a.Order_Completion_Date__c.year()));
               Yearset.add(String.ValueOf(a.Order_Completion_Date__c.year()+1));
              }
         
        else If(a.SOLO_Submitted_Date__c != NULL){
               Yearset.add(String.ValueOf(a.SOLO_Submitted_Date__c.year()));
               Yearset.add(String.ValueOf(a.SOLO_Submitted_Date__c.year()+1));
              }
          else If(a.Order_Date_SOLO__c != NULL){
               Yearset.add(String.ValueOf(a.Order_Date_SOLO__c.year()));
               Yearset.add(String.ValueOf(a.Order_Date_SOLO__c.year()+1));
              }
          else{
               Yearset.add(String.ValueOf(a.CloseDate.year()));
               Yearset.add(String.ValueOf(a.CloseDate.year()+1));
              }
    }
        //Putting the Booking date records in a map for this year and next year
        integer i = 0;
        for(Booking_Dates__c  bookingDate:[select Id,Booking_Closing_Year1__c,Booking_Closing_Month__c,Booking_Closing_Date__c from Booking_Dates__c where Booking_Closing_Year1__c IN: Yearset ORDER BY Booking_Closing_Date__c ASC]){
                    i=i+1;
                    
                     
                     bookingdatesmap.put(bookingDate.Booking_Closing_Month__c+bookingDate.Booking_Closing_Year1__c,bookingDate.Booking_Closing_Date__c);
                     MonthList.add(bookingDate.Booking_Closing_Month__c+bookingDate.Booking_Closing_Year1__c);
                     MonthYearMap.put(bookingDate.Booking_Closing_Month__c+bookingDate.Booking_Closing_Year1__c,Integer.ValueOf(bookingDate.Booking_Closing_Month__c));
                     
                
                }
                //Loop through the Opportunities and populate the Booked Date and Booking closing date
                     for(Opportunity Opty :Opptys){
                         if(Limits.getHeapSize() < 0.81*Limits.getLimitHeapSize()){
                             Date submissiondate;
                             //Boolean BookingNull = False;
                             //Updated this Line for completion Date Check
                               If(Opty.Order_Completion_Date__c != NULL){
                                   submissiondate=Opty.Order_Completion_Date__c; 
                               }
                               else If(Opty.SOLO_Submitted_Date__c != NULL){
                                   submissiondate=Opty.SOLO_Submitted_Date__c;
                                 }
                               else If(Opty.Order_Date_SOLO__c != NULL){
                                   submissiondate=Opty.Order_Date_SOLO__c;
                               }
                               else{
                                   submissiondate=Opty.CloseDate;
                               }
                             system.debug('TEST SUBMISSION'+submissiondate); 
                             System.Debug('MAP TEST'+bookingdatesmap);
                             for(integer j=0;j<bookingdatesmap.size();j++){ 
                                 month = MonthList[j];
                                If(bookingdatesmap.ContainsKey(String.ValueOf(submissiondate.Month())+String.ValueOf(submissiondate.Year()))){
                                 if(Opty.Order_Completion_Date__c != NULL){
                                 
                                         if(((Opty.Order_Completion_Date__c==bookingdatesmap.get(month ))||(Opty.Order_Completion_Date__c<bookingdatesmap.get(month)))){
                                             Opty.Booking_Closing_Date__c = bookingdatesmap.get(month);
                                              
                                           
                                              integer noOfDays = Date.daysInMonth(submissiondate.year(), MonthYearMap.get(month));
                                              Opty.Booked_Date__c = Date.newInstance(submissiondate.year(),MonthYearMap.get(month), noOfDays);
                                            
                                                                                                                                    
                                             OpptystoUpdate.add(Opty);
                                             break;
                                         }
                                         else{
                                            Opty.Booking_Closing_Date__c = NULL;
                                            Opty.Booked_Date__c = NULL;                                          
                                         }
                                                                                  
                                    }
                                    // This code is when completion date is null
                                    else{
                                        If((String.ValueOf(submissiondate.Month())+String.ValueOf(submissiondate.Year())==month)){
                                             Opty.Booking_Closing_Date__c = bookingdatesmap.get(month);
                                              if(bookingdatesmap.get(month) != NULL){
                                              
                                              integer noOfDays = Date.daysInMonth(submissiondate.year(), MonthYearMap.get(month));
                                              Opty.Booked_Date__c = Date.newInstance(submissiondate.year(),MonthYearMap.get(month), noOfDays);
                                              
                                             }                                                                                          
                                             OpptystoUpdate.add(Opty);
                                             break;
                                         }
                                         else{
                                         Opty.Booking_Closing_Date__c = NULL;
                                         Opty.Booked_Date__c = NULL;
                                         }

                                    }     
                                   } 
                                
                               }       
                             }
                             else{
                                 break;
                             }
                         }
 
                   if(Opptys.Size()>0)
                   {
                     try{
                         Update Opptys; 
                         }
                         catch(DMLException exe){
                         GeneralConstants.mailAnyExceptionToMe('OOROrderBookingDatesUpdate','Trigger firing the batch apex on Booking Dates',exe);
                        }
                    }


}
global void finish(Database.BatchableContext BC){
}
}